package com.qd.panda.hk;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cdqidi.dto.ApiResult;
import com.cdqidi.dto.ApiResultWrapper;
import com.cdqidi.exception.ApiException;
import com.cdqidi.repeat.annotation.RepeatSubmit;
import com.cdqidi.util.LockTemplate;
import com.cdqidi.util.page.PageUtil;
import com.qd.common.panda.constant.PandaConstant;
import com.qd.common.panda.domain.entity.hk.HkArrearsRecordsDataReq;
import com.qd.common.panda.domain.entity.hk.HkParkOrderDTO;
import com.qd.common.panda.domain.entity.hk.HkPaymentInfoReq;
import com.qd.common.panda.domain.entity.hk.HkUserDTO;
import com.qd.common.panda.domain.entity.stroke.PayParamDTO;
import com.qd.common.sys.domain.login.LoginUser;
import com.qd.common.sys.util.SecurityUtils;
import com.qd.hik.dto.HkBaseHttpResp;
import com.qd.hik.dto.charge.*;
import com.qd.hik.dto.invoice.*;
import com.qd.hik.service.HkChargeService;
import com.qd.hik.service.HkInvoiceService;
import com.qd.panda.service.hk.HkParkOrderService;
import com.qd.panda.service.hk.HkService;
import com.qd.panda.service.third.hk.HkUserService;
import com.qd.panda.service.wallet.user.WalletService;
import com.qd.system.service.person.AuthTokenService;
import com.qd.system.service.user.BaseUserInfoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.*;

/**
 * APP_海康停车
 *
 * @author sjk
 */
@RestController
@RequiredArgsConstructor
@Validated
@RequestMapping("/app/hkParkInfo/")
@Slf4j
public class AppHkController {

    private final HkChargeService hkChargeService;
    private final HkUserService hkUserService;
    private final HkInvoiceService hkInvoiceService;
    private final BaseUserInfoService baseUserInfoService;
    private final HkService hkService;
    private final WalletService walletService;
    private final AuthTokenService authTokenService;
    private final HkParkOrderService hkParkOrderService;

    private final HttpServletRequest request;

    /**
     * 在停订单查询
     */
    @GetMapping(value = "/parkOrdersParking")
    public List<HkPaymentInfoResp> parkOrdersParking(String plateNo) {
        return hkService.parkOrdersParking(plateNo);
    }

    /**
     * 停车订单列表
     *
     * @param requestType 请求类型，1-正在停车，2-欠费补缴，3-已完成
     * @return 列表
     */
    @GetMapping(value = "/parkOrders")
    public Set<HkParkOrdersResp.Results> parkOrders(@Validated @NotNull(message = "请求类型不能为空") Integer requestType, String phone) {
        if (!StringUtils.hasLength(phone)) {
            phone = SecurityUtils.getLoginUser().getUser().getAppUserExtend().getMobile();
        }
        Set<HkParkOrdersResp.Results> set = new HashSet<>();
        hkChargeService.parkOrders(1, requestType, phone, set);
        log.info("停车订单列表，phone： {},数量: {}", phone, set.size());
        return set;
    }

    /**
     * 可使用的优惠券列表
     *
     * @param uniqueId 订单标识
     * @param parkCode 停车场编号
     * @return 列表
     */
    @GetMapping(value = "/usableCoupons")
    public List<HkUsableCouponsResp> usableCoupons(@Validated @NotBlank(message = "订单标识不能为空") String uniqueId, @NotBlank(message = "停车场编号不能为空") String parkCode) {
        HkUsableCouponsReq req = new HkUsableCouponsReq();
        req.setUniqueId(uniqueId);
        req.setParkCode(parkCode);
        req.setPhone(SecurityUtils.getLoginUser().getUser().getAppUserExtend().getMobile());
        final HkBaseHttpResp<List<HkUsableCouponsResp>> resp = hkChargeService.parkOrdersUsableCoupons(req);
        req.freeData();
        if (resp.isSuccess()) {
            return resp.getData();
        } else {
            throw new ApiException(resp.getMsg());
        }
    }

    /**
     * 临停缴费下单
     *
     * @param req 请求参数
     * @return 支付参数
     */
    @RepeatSubmit
    @PostMapping(value = "/payment")
    public ApiResultWrapper<Object> payment(@Validated @RequestBody HkPaymentInfoReq req) {
        Integer wallet = Optional.ofNullable(req.getWallet()).orElse(PandaConstant.PAY_METHOD_WX);
        if (wallet.equals(PandaConstant.PAY_METHOD_WX)) {
            return ApiResult.success(hkService.createOrder(req));
        } else if (wallet.equals(PandaConstant.PAY_METHOD_WALLET)) {
            //钱包支付
            LoginUser loginUser = authTokenService.getLoginUser(request);
            if (null == loginUser) {
                return ApiResult.error("未登录不支持钱包支付");
            }
//            RedissonLockTemplate.execute(loginUser.getUserId(), () -> {
//                walletService.payment(loginUser, req);
//                return null;
//            }, 10, 60);
            PayParamDTO payParamDTO = LockTemplate.execute(loginUser.getUserId(), () -> walletService.payment(loginUser, req));
            return ApiResult.success(payParamDTO);
        } else {
            return ApiResult.error("不支持的支付方式");
        }
    }

    /**
     * 批量补缴下单
     *
     * @param req 请求参数
     * @return 支付参数
     */
    @RepeatSubmit
    @PostMapping(value = "/paymentBatch")
    public ApiResultWrapper<Object> paymentBatch(@Validated @RequestBody HkArrearsRecordsDataReq req) {
        Integer wallet = Optional.ofNullable(req.getWallet()).orElse(PandaConstant.PAY_METHOD_WX);
        if (wallet.equals(PandaConstant.PAY_METHOD_WX)) {
            return ApiResult.success(hkService.arrears(req));
        } else if (wallet.equals(PandaConstant.PAY_METHOD_WALLET)) {
            //钱包支付
            LoginUser loginUser = authTokenService.getLoginUser(request);
            if (null == loginUser) {
                return ApiResult.error("未登录不支持钱包支付");
            }
//            RedissonLockTemplate.execute(loginUser.getUserId(), () -> {
//                walletService.paymentBatch(loginUser, req);
//                return null;
//            }, 10, 60);
            PayParamDTO payParamDTO = LockTemplate.execute(loginUser.getUserId(), () -> walletService.paymentBatch(loginUser, req));
            return ApiResult.success(payParamDTO);
        } else {
            return ApiResult.error("不支持的支付方式");
        }
    }

    /**
     * 提交订单申诉
     *
     * @param req 请求参数
     * @return true or false
     */
    @PostMapping(value = "/parkOrdersAppeal")
    public ApiResultWrapper<Object> parkOrdersAppeal(@Validated @RequestBody HkParkOrdersAppealReq req) {
        req.setPhone(SecurityUtils.getLoginUser().getUser().getAppUserExtend().getMobile());
        final HkBaseHttpResp<?> resp = hkChargeService.parkOrdersAppeal(req);
        req.freeData();
        if (resp.isSuccess()) {
            return ApiResult.success();
        }
        throw new ApiException(resp.getMsg());
    }

    /**
     * 订单申诉详情
     *
     * @param uniqueId 订单ID
     * @param parkCode 停车场编号
     * @return 详情
     */
    @PostMapping(value = "/appealDetail")
    public HkAppealDetailResp appealDetail(@Validated @NotBlank(message = "订单标识不能为空") String uniqueId, @NotBlank(message = "停车场编号不能为空") String parkCode) {
        final HkBaseHttpResp<HkAppealDetailResp> resp = hkChargeService.appealDetail(uniqueId, parkCode);
        if (resp.isSuccess()) {
            return resp.getData();
        }
        throw new ApiException(resp.getMsg());
    }

    /**
     * 车牌欠费记录
     *
     * @param plateNo 车牌号
     * @return 列表
     */
    @GetMapping(value = "/getArrearsRecords")
    public List<HkArrearsRecordsResp> getArrearsRecords(@Validated String plateNo) {
        return hkService.getArrearsRecords(plateNo);
    }

    /**
     * 停车订单列表-分页
     *
     * @param requestType 请求类型，1-正在停车，2-欠费补缴，3-已完成
     * @return 列表
     */
    @GetMapping(value = "/parkOrdersPage")
    public IPage<HkParkOrdersResp.Results> parkOrdersPage(@Validated @NotNull(message = "请求类型不能为空") Integer requestType, Integer pageNumber, Integer pageSize) {
        HkParkOrdersReq req = new HkParkOrdersReq();
        req.setPhone(SecurityUtils.getLoginUser().getUser().getAppUserExtend().getMobile());
        req.setRequestType(requestType + "");
        req.setPageNo(pageNumber);
        req.setPageSize(pageSize);
        HkBaseHttpResp<HkParkOrdersResp> resp = hkChargeService.parkOrders(req);
        req.freeData();
        if (resp.isSuccess()) {
            HkParkOrdersResp data = resp.getData();
            if (null == data.getResults() || data.getResults().isEmpty()) {
                return new Page<>();
            }
            IPage<HkParkOrdersResp.Results> page = new Page<>(data.getPageNo(), pageSize);
            page.setRecords(data.getResults());
            page.setTotal((long) data.getResults().size() * data.getTotalPage());
            return page;
        } else {
            throw new ApiException("查询停车订单列表失败: " + resp.getMsg());
        }
    }

    /**
     * 可开票停车账单
     *
     * @param phone      手机号
     * @param pageNumber 页数
     * @param pageSize   每页条数
     */
    @GetMapping("/invoiceAbleParkingBills")
    public IPage<HkInvoiceAbleParkingBillsResp.Result> invoiceAbleParkingBills(String phone, Integer pageNumber, Integer pageSize) {
        String userId;
        if (StringUtils.hasLength(phone)) {
            userId = baseUserInfoService.getMobileToUid(phone);
            if (!StringUtils.hasLength(userId)) {
                throw new ApiException("手机号没有对应的用户信息");
            }
        } else {
            userId = SecurityUtils.getLoginUser().getUserId();
        }
        HkUserDTO hkUserDTO = hkUserService.getByIdDto(userId);
        if (hkUserDTO == null) {
            throw new ApiException("用户不存在");
        }
        Integer driverId = hkUserDTO.getDriverId();

        HkInvoiceAbleParkingBillsReq req = new HkInvoiceAbleParkingBillsReq();
        req.setDriverId(driverId);
        req.setPageNo(pageNumber);
        req.setPageSize(pageSize);
        HkBaseHttpResp<HkInvoiceAbleParkingBillsResp> resp = hkInvoiceService.invoiceAbleParkingBills(req);
        req.freeData();
        if (resp.isSuccess()) {
            if (null == resp.getData()) {
                return new Page<>();
            } else {
                List<HkInvoiceAbleParkingBillsResp.Result> results = resp.getData().getResults();
                IPage<HkInvoiceAbleParkingBillsResp.Result> page = new Page<>(resp.getData().getPageNo(), pageSize);
                page.setRecords(results);
                page.setTotal((long) results.size() * resp.getData().getTotalPage());
                return page;
            }
        } else {
            throw new ApiException("可开票停车账单失败: " + resp.getMsg());
        }
    }

    /**
     * 获取开票地址
     *
     * @param req 请求参数
     * @return 开票地址
     */

    @PostMapping("/getInvoiceUrl")
    public ApiResultWrapper<Object> getInvoiceUrl(@Validated @RequestBody HkGetInvoiceReq req) {
        String userId = SecurityUtils.getLoginUser().getUserId();
        HkUserDTO hkUserDTO = hkUserService.getByIdDto(userId);
        if (hkUserDTO == null) {
            throw new ApiException("用户不存在");
        }
        Integer driverId = hkUserDTO.getDriverId();
        req.setDriverId(driverId);
        HkBaseHttpResp<HkGetInvoiceResp> resp = hkInvoiceService.getInvoiceUrl(req);
        req.freeData();
        if (resp.isSuccess()) {
            return ApiResult.success(resp.getData().getInvoiceUrl());
        } else {
            return ApiResult.error("获取开票地址失败: " + resp.getMsg());
        }
    }

    /**
     * 获取开票记录
     *
     * @param pageNumber 页数
     * @param pageSize   每页条数
     */
    @GetMapping("/invoiceRecords")
    public IPage<HkInvoiceDetailResp> invoiceRecords(Integer pageNumber, Integer pageSize) {
        String userId = SecurityUtils.getLoginUser().getUserId();
        HkUserDTO hkUserDTO = hkUserService.getByIdDto(userId);
        if (hkUserDTO == null) {
            throw new ApiException("用户不存在");
        }
        Integer driverId = hkUserDTO.getDriverId();
        HkInvoiceAbleParkingBillsReq req = new HkInvoiceAbleParkingBillsReq();
        req.setDriverId(driverId);
        req.setPageNo(pageNumber);
        req.setPageSize(pageSize);
        HkBaseHttpResp<HkInvoiceRecordsResp> resp = hkInvoiceService.invoiceRecords(req);
        req.freeData();
        if (resp.isSuccess()) {
            if (null == resp.getData()) {
                return new Page<>();
            } else {
                List<HkInvoiceDetailResp> results = resp.getData().getResults();
                IPage<HkInvoiceDetailResp> page = new Page<>(resp.getData().getPageNo(), pageSize);
                page.setRecords(results);
                page.setTotal((long) results.size() * resp.getData().getTotalPage());
                return page;
            }
        } else {
            throw new ApiException("获取开票记录失败: " + resp.getMsg());
        }
    }

    /**
     * 获取开票详情
     *
     * @param groupId   开票账户
     * @param invoiceId 开票申请ID
     */
    @GetMapping("/invoiceDetail")
    public HkInvoiceDetailResp invoiceDetail(@Validated @NotNull(message = "开票账户不能为空") Integer groupId, @NotNull(message = "开票申请ID不能为空") Integer invoiceId) {
        String userId = SecurityUtils.getLoginUser().getUserId();
        HkUserDTO hkUserDTO = hkUserService.getByIdDto(userId);
        if (hkUserDTO == null) {
            throw new ApiException("用户不存在");
        }
        Integer driverId = hkUserDTO.getDriverId();
        HkInvoiceDetailReq req = new HkInvoiceDetailReq();
        req.setDriverId(driverId);
        req.setGroupId(groupId);
        req.setInvoiceId(invoiceId);
        HkBaseHttpResp<HkInvoiceDetailResp> resp = hkInvoiceService.invoiceDetail(req);
        req.freeData();
        if (resp.isSuccess()) {
            return resp.getData();
        } else {
            throw new ApiException("获取开票详情失败: " + resp.getMsg());
        }
    }

    /**
     * 支付失败
     *
     * @param map 业务ID
     */
    @PostMapping("/payError")
    public ApiResultWrapper<Object> payError(@Validated @RequestBody Map<String, String> map) {
        String bid = map.get("thirdPartyOrder");
        if (!StringUtils.hasLength(bid)) {
            return ApiResult.error("业务ID不能为空");
        }
        hkService.payError(bid);
        return ApiResult.success();
    }

    /**
     * 支付详情
     *
     * @param thirdPartyOrder 业务ID
     * @return 详情
     */
    @GetMapping("/payDetail")
    public ApiResultWrapper<Object> payDetail(@Validated @NotNull(message = "业务ID不能为空") String thirdPartyOrder) {
        return ApiResult.success(hkService.payDetail(thirdPartyOrder));
    }

    /**
     * 可开票停车订单
     */
    @GetMapping("/invoicablePage")
    public IPage<HkParkOrderDTO> invoicablePage(HkParkOrderDTO dto) {
        String userId = SecurityUtils.getLoginUser().getUserId();
        dto = Optional.ofNullable(dto).orElse(new HkParkOrderDTO());
        dto.setUserId(userId);
        return hkParkOrderService.invoicablePage(PageUtil.buildPage(dto), dto);
    }
}
